<script lang="ts" setup>
import type { TreeNode } from '@vben/types';

import type { VbenFormProps, VxeGridProps } from '#/adapter';

import { h, ref } from 'vue';

import { Page, useVbenModal } from '@vben/common-ui';

import {
  DeleteOutlined,
  EditOutlined,
  MoreOutlined,
  PlusCircleOutlined,
} from '@ant-design/icons-vue';
import { Icon } from '@iconify/vue/dist/iconify.js';
import {
  Button,
  Dropdown,
  Input,
  Menu,
  message,
  Popconfirm,
  Tree,
} from 'ant-design-vue';

import { useVbenVxeGrid } from '#/adapter';
import {
  deleteMenuApi,
  getMenuDetailApi,
  getMenuListApi,
  getMenuTreeApi,
  updateMenuPositionApi,
} from '#/api/core/menu';
import { $t } from '#/locales';

import MenuModalComp from './menu-modal.vue';

const leftFormOptions: VbenFormProps = {
  schema: [],
};

const selectedMenuKey = ref<number | string>('1');
// 添加一个变量存储当前的查询条件
const currentQueryParams = ref({});

interface MenuType {
  id: number;
  parentId: number;
  title: string; // 菜单名
  name: string; // 菜单别名
  component: string; // 组件
  path: string; // 路径
  icon: string; // 图标
  code: string; // 权限码
  description: string; // 描述
}

const treeData = ref<TreeNode[]>([]);
const filteredTreeData = ref<TreeNode[]>([]);
const expandedKeys = ref<(number | string)[]>([]);
const searchText = ref('');
const selectedRows = ref<MenuType[]>([]);

const [MenuModal, menuModalApi] = useVbenModal({
  connectedComponent: MenuModalComp,
});

const gridOptions: VxeGridProps<MenuType> = {
  checkboxConfig: {
    highlight: true,
    labelField: 'name',
  },
  columns: [
    { field: 'title', title: $t('menu.columns.title') },
    { field: 'name', title: $t('menu.columns.name') },
    { field: 'path', title: $t('menu.columns.path') },
    { field: 'component', title: $t('menu.columns.component') },
    {
      field: 'icon',
      title: $t('menu.columns.icon'),
      slots: {
        default: ({ row }) => {
          return [
            h('div', { class: 'flex justify-center items-center' }, [
              row.icon ? h(Icon, { icon: row.icon, class: 'text-lg' }) : null,
            ]),
          ];
        },
      },
    },
    { field: 'code', title: $t('menu.columns.code') },
    { field: 'description', title: $t('menu.columns.description') },
  ],
  height: 'auto',
  keepSource: true,
  pagerConfig: {},
  proxyConfig: {
    ajax: {
      query: async ({ page }) => {
        const params = {
          ...currentQueryParams.value,
          page: Number(page.currentPage),
          pageSize: Number(page.pageSize),
          id: selectedMenuKey.value,
        };
        return await getMenuListApi(params);
      },
    },
  },
};

const [Grid, gridApi] = useVbenVxeGrid({ gridOptions });

// 修改加载树数据的函数
function processTreeData(nodes: any[]): TreeNode[] {
  return nodes.map((node) => ({
    key: node.id,
    title: node.title || node.name,
    pid: node.parentId,
    children: node.children ? processTreeData(node.children) : undefined,
    ...node,
  }));
}

// 修改加载树数据的函数
async function loadMenuTree() {
  try {
    const data = await getMenuTreeApi();
    if (data && Array.isArray(data)) {
      treeData.value = processTreeData(data);
      filteredTreeData.value = treeData.value;
      if (treeData.value.length > 0 && treeData.value[0]?.key !== undefined) {
        expandedKeys.value = [treeData.value[0].key];
      }
    } else {
      treeData.value = [];
      filteredTreeData.value = [];
    }
  } catch (error) {
    treeData.value = [];
    filteredTreeData.value = [];
    message.error($t('menu.tree.loadFailed'));
  }
}

// 组件挂载时加载菜单树
loadMenuTree();

// 过滤树节点的函数
function filterTreeNode(nodes: TreeNode[], keyword: string): TreeNode[] {
  return nodes
    .map((node) => {
      // 如果节点标题包含关键字，直接返回该节点及其所有子节点
      if (node.title.toLowerCase().includes(keyword.toLowerCase())) {
        return { ...node };
      }

      // 如果有子节点，递归过滤子节点
      if (node.children?.length) {
        const filteredChildren = filterTreeNode(node.children, keyword);
        // 如果过滤的子节点不为空，返回当前节点及过滤后的子节点
        if (filteredChildren.length > 0) {
          return {
            ...node,
            children: filteredChildren,
          };
        }
      }

      return null;
    })
    .filter((node): node is TreeNode => node !== null);
}

function handleSearch(value = '') {
  const searchValue = value;
  searchText.value = searchValue;
  if (!searchValue.trim()) {
    filteredTreeData.value = treeData.value;
    return;
  }
  filteredTreeData.value = filterTreeNode(treeData.value, searchValue);
}

// 修改树节点选择处理函数
function handleTreeSelect(selectedKeys: (number | string)[], info: any) {
  // 如果是取消选择，则不更新 selectedMenuKey
  if (!info.selected) {
    return;
  }
  selectedMenuKey.value = selectedKeys[0] || '1';
  // 更新查询参数，添加id
  currentQueryParams.value = {
    id: selectedMenuKey.value,
  };
  // 重新加载表格数据
  gridApi.reload();
}

// 展开全部
function expandAll() {
  const allKeys: (number | string)[] = [];
  const getKeys = (nodes: TreeNode[]) => {
    nodes.forEach((node) => {
      allKeys.push(node.key); // 不需要转换为字符串
      if (node.children?.length) {
        getKeys(node.children);
      }
    });
  };
  getKeys(treeData.value);
  expandedKeys.value = allKeys;
}

// 折叠全部
function collapseAll() {
  expandedKeys.value = [];
}

async function handleAddMenu(key: number | string) {
  const currentNode = findNodeInTree(treeData.value, key);
  if (currentNode) {
    menuModalApi.setData({
      isEdit: false,
      id: key,
      parentId: currentNode.parentId,
      editData: null,
      rootNode: key === 0,
    });
    menuModalApi.setState({ title: $t('menu.add') });
    menuModalApi.open();
  }
}

async function handleEditMenu(key: number | string) {
  try {
    const menuData = await getMenuDetailApi(key);
    const editData = {
      id: menuData.id,
      parentId: menuData.parentId,
      title: menuData.title,
      name: menuData.name,
      component: menuData.component,
      path: menuData.path,
      icon: menuData.icon,
      code: menuData.code,
      sort: menuData.sort,
      description: menuData.description,
      redirect: menuData.redirect,
    };

    menuModalApi.setData({
      isEdit: true,
      id: key,
      parentId: menuData.parentId,
      editData,
      rootNode: menuData.parentId === 0,
    });
    menuModalApi.setState({ title: $t('menu.edit') });
    menuModalApi.open();
  } catch {
    throw new Error($t('menu.save.failed'));
  }
}

// 添加一个辅助函数来在树中查找节点
function findNodeInTree(
  nodes: TreeNode[],
  key: number | string,
): null | TreeNode {
  for (const node of nodes) {
    if (node.key === key) {
      return node;
    }
    if (node.children?.length) {
      const found = findNodeInTree(node.children, key);
      if (found) return found;
    }
  }
  return null;
}

async function handleSaveMenu() {
  await loadMenuTree();
  gridApi.reload(); // 刷新用户列表
}

function handleSave() {
  gridApi.reload();
}

const gridEvents = {
  checkboxChange({ records }: { records: MenuType[] }) {
    selectedRows.value = records;
  },
  checkboxAll({ records }: { records: MenuType[] }) {
    selectedRows.value = records;
  },
};

async function handleDeleteMenu(key: number | string) {
  try {
    await deleteMenuApi(key);
    await loadMenuTree();
    gridApi.reload();
  } catch (error) {
    console.error('删除菜单失败:', error);
  }
}

// 判断是否允许放置
function allowDrop(_params: any) {
  return true; // 允许所有拖放操作
}

// 处理拖放完成事件
async function onDrop({ dragNode, node: dropNode, dropPosition }: any) {
  try {
    // 根据 dropPosition 确定拖放类型
    const dropType = dropPosition === 0 ? 'sub' : 'same';

    // 调用后端 API 更新节点位置
    await updateMenuPositionApi({
      dragId: Number(dragNode.key),
      dropId: Number(dropNode.key),
      dropPosition,
      dropType,
    });

    // 重新加载树数据
    await loadMenuTree();
    message.success($t('menu.move.success'));
  } catch {
    message.error($t('menu.move.failed'));
    // 发生错误时重新加载树以恢复原状
    await loadMenuTree();
  }
}
</script>

<template>
  <Page auto-content-height>
    <BaseDrawer :on-save="handleSave" />
    <Grid :grid-events="gridEvents" :tree-node-options="leftFormOptions">
      <!-- 添加左侧区域插槽 -->
      <template #left-area>
        <div class="flex h-full flex-col">
          <!-- 搜索框和更多按钮的容器 -->
          <div class="mb-2 flex items-center">
            <Input.Search
              v-model:value="searchText"
              :placeholder="$t('common.search')"
              allow-clear
              class="flex-1"
              @change="(e) => handleSearch(e.target.value)"
              @search="handleSearch"
            />
            <Dropdown>
              <Button class="ml-2">
                <MoreOutlined />
              </Button>
              <template #overlay>
                <Menu>
                  <Menu.Item @click="expandAll">
                    {{ $t('common.expandAll') }}
                  </Menu.Item>
                  <Menu.Item @click="collapseAll">
                    {{ $t('common.collapseAll') }}
                  </Menu.Item>
                </Menu>
              </template>
            </Dropdown>
          </div>

          <!-- 树组件 -->
          <div class="flex-1 overflow-auto">
            <Tree
              :allow-drop="allowDrop"
              :expanded-keys="expandedKeys"
              :field-names="{
                title: 'title',
                key: 'key',
                children: 'children',
              }"
              :selected-keys="[selectedMenuKey]"
              :tree-data="filteredTreeData"
              draggable
              @drop="onDrop"
              @expand="(keys) => (expandedKeys = keys)"
              @select="handleTreeSelect"
            >
              <template #title="{ title, key }">
                <div
                  class="tree-node-wrapper"
                  @click="
                    () => console.log('Node key:', key, 'Type:', typeof key)
                  "
                >
                  <span>{{ title }}</span>
                  <div class="tree-node-actions">
                    <template v-if="key <= 11">
                      <a class="action-link" @click.stop="handleAddMenu(key)">
                        <PlusCircleOutlined class="action-icon" />
                      </a>
                    </template>

                    <template v-else>
                      <a class="action-link" @click.stop="handleAddMenu(key)">
                        <PlusCircleOutlined class="action-icon" />
                      </a>
                      <a class="action-link" @click.stop="handleEditMenu(key)">
                        <EditOutlined class="action-icon" />
                      </a>
                      <Popconfirm
                        :title="$t('menu.delete.confirm')"
                        placement="bottomRight"
                        @click.stop
                        @confirm="handleDeleteMenu(key)"
                      >
                        <a class="action-link">
                          <DeleteOutlined class="action-icon" />
                        </a>
                      </Popconfirm>
                    </template>
                  </div>
                </div>
              </template>
            </Tree>
          </div>
        </div>
      </template>
    </Grid>
    <MenuModal @save="handleSaveMenu" />
  </Page>
</template>

<style scoped>
.tree-node-wrapper {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
  padding-right: 8px;
}

:deep(.ant-tree-node-content-wrapper) {
  width: 100%;
}

:deep(.ant-tree-node-selected) {
  width: 100%;
}

.tree-node-actions {
  position: absolute;
  right: 0;
  z-index: 1;
  display: none;
  align-items: center;
  height: 100%;
  white-space: nowrap;
  background: transparent;
}

.tree-node-wrapper:hover .tree-node-actions {
  display: flex;
  gap: 4px;
  padding-right: 16px;
  padding-left: 8px;
  background: transparent;
}

/* 操作链接样式 */
.action-link {
  display: flex;
  align-items: center;
  padding: 4px;
  color: rgb(0 0 0 / 45%);
  background: transparent;
  transition: color 0.3s;
}

.action-link:hover {
  color: #1890ff;
  background: transparent;
}

.action-icon {
  font-size: 14px;
}

/* 防止节点文字与钮重叠 */
.tree-node-wrapper > span {
  padding-right: 90px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
</style>
